package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.domain.db.User;
import com.itheima.domain.db.UserFreeze;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.FocusUser;
import com.itheima.domain.mongo.Video;
import com.itheima.domain.vo.CommentVo;
import com.itheima.domain.vo.PageBeanVo;
import com.itheima.domain.vo.VideoVo;
import com.itheima.service.db.UserFreezeService;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.CommentService;
import com.itheima.service.mongo.FocusUserService;
import com.itheima.service.mongo.VideoService;
import com.itheima.util.ConstantUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.lang.invoke.VolatileCallSite;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class VideoManager {

    @Reference
    private VideoService videoService;

    @Reference
    private UserInfoService userInfoService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private OssTemplate ossTemplate;
    @Reference
    private FocusUserService focusUserService;
    @Reference
    private CommentService commentService;
    @Autowired
    private MQVideoManager mqVideoManager;
    @Autowired
    private FastFileStorageClient client;  //存储的客户端  注入会报错 , 不影响执行
    @Autowired
    private FdfsWebServer webServer; // tracker的服务器  注入会报错 , 不影响执行
    @Reference
    private UserFreezeService userFreezeService;


    /**
     * 查询小视频列表
     *
     * @param pageNumber
     * @param pageSize
     * @return
     */
    @Cacheable(value = "video", key = "'video_'+#pageNumber+'_'+#pageSize")
    public PageBeanVo findVideo(Integer pageNumber, Integer pageSize) {
        //1.获得当前用户id
        Long loginUserId = UserHolder.getId();

        //2.查询小视频的列表
        PageBeanVo pageBeanVo = videoService.findVideoByUserId(pageNumber, pageSize, loginUserId);

        List<Video> items = (List<Video>) pageBeanVo.getItems(); //可以设置假数据
        List<VideoVo> videoVoList = new ArrayList();
        //3.封装vo  items - >  videoVoList
        if (CollectionUtil.isNotEmpty(items)) {
            for (Video video : items) {
                //3.1.查询到个人信息
                UserInfo userInfo = userInfoService.findById(video.getUserId());
                //3.2 创建vo对象
                VideoVo videoVo = new VideoVo();
                //3.3 封装UserInfo userId封装不了
                BeanUtil.copyProperties(userInfo, videoVo);
                //videoVo.setUserId( userInfo.getId() ); //手动赋值 用户的id

                //3.4 封装video
                BeanUtil.copyProperties(video, videoVo);
                videoVo.setCover(video.getPicUrl()); //封面
                videoVo.setVideoUrl(video.getVideoUrl()); //视频
                videoVo.setSignature(video.getText());//文本 标题

                //设置是否关注
                String key = StrUtil.format(ConstantUtil.FOCUS_USER, UserHolder.getId(), video.getUserId());
                if (stringRedisTemplate.hasKey(key)) { //关注过
                    videoVo.setHasFocus(1);
                }
                String key1 = StrUtil.format(ConstantUtil.VIDEO_LIKE, loginUserId, video.getId());
                if (stringRedisTemplate.hasKey(key1)) {
                    videoVo.setHasLiked(1);
                } else {
                    videoVo.setHasLiked(0);
                }
                videoVoList.add(videoVo);
            }
        }

        pageBeanVo.setItems(videoVoList);
        return pageBeanVo;
    }

    /**
     * 保存小视频
     *
     * @param videoThumbnail
     * @param videoFile
     */
    @CacheEvict(value = "video", allEntries = true)
    public void saveVideo(MultipartFile videoThumbnail, MultipartFile videoFile) throws IOException {
        //1.保存封面 -oss
        String picUrl = "https://" + ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());
        //2.保存视频 -fastDFS
        StorePath storePath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), FileUtil.extName(videoFile.getOriginalFilename()), null);
        String videoUrl = webServer.getWebServerUrl() + storePath.getFullPath();//拼接文件路径
        System.err.println("------->>>" + videoUrl);
        //3.构建Video对象
        Video video = new Video();
        video.setUserId(UserHolder.getId());//当前登录用户
        video.setText("左手右手一个慢动作!");
        video.setPicUrl(picUrl); //封面路径
        video.setVideoUrl(videoUrl);//视频路径
        //4.保存数据
        ObjectId objectId = videoService.saveVideo(video);
        mqVideoManager.sendVideoMsg(objectId.toHexString(), MQVideoManager.VIDEO_PUBLISH);

    }

    /**
     * 删除视频关注
     *
     * @param videoUserId
     */
    @CacheEvict(value = "video", allEntries = true)
    public void deleteUserFocus(Long videoUserId) {
        //当前用户id
        Long loginUserId = UserHolder.getId();

        //删除记录
        focusUserService.deleteUserFocus(loginUserId, videoUserId);

        //删除缓存
        String key = StrUtil.format(ConstantUtil.FOCUS_USER, UserHolder.getId(), videoUserId);
        stringRedisTemplate.delete(key);
    }

    /**
     * 添加视频关注
     *
     * @param videoUserId
     */
    @CacheEvict(value = "video", allEntries = true)
    public void saveUserFocus(Long videoUserId) {
        //构建对象
        FocusUser focusUser = new FocusUser();
        focusUser.setUserId(UserHolder.getId());//自己的id
        focusUser.setFocusUserId(videoUserId); //视频发布者的id

        //直接保存
        focusUserService.saveUserFocus(focusUser);

        //存入缓存中
        // 谁关注了谁  99_2
        String key = StrUtil.format(ConstantUtil.FOCUS_USER, UserHolder.getId(), videoUserId);
        stringRedisTemplate.opsForValue().set(key, "1");

    }

    //视频点赞
    @CacheEvict(value = "video", allEntries = true)
    public Integer saveVideoLike(String videoId) {
        //1.构建comment对象
        Comment comment = new Comment();
        //2.comment保存对象
        comment.setPublishId(new ObjectId(videoId));
        comment.setCommentType(4);
        comment.setUserId(UserHolder.getId());
        Integer integer = commentService.saveVideoComment(comment);
        //3.将数据存入redis中
        String format = StrUtil.format(ConstantUtil.VIDEO_LIKE, UserHolder.getId(), videoId);

        stringRedisTemplate.opsForValue().set(format, "4");  //值随便

        mqVideoManager.sendVideoMsg(videoId, MQVideoManager.VIDEO_LIKE);
        return integer;
    }

    //取消视频点赞
    @CacheEvict(value = "video", allEntries = true)
    public Integer dislikeVideo(String videoId) {
        //1. 组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(videoId));//视频id
        comment.setCommentType(4);//点赞
        comment.setUserId(UserHolder.getId());//操作人id

        //2. 调用service完成取消点赞
        Integer integer = commentService.deleteVideoComment(comment);

        //3. 向redis中删除点赞操作
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.VIDEO_LIKE, UserHolder.getId(), videoId));

        mqVideoManager.sendVideoMsg(videoId, MQVideoManager.VIDEO_DISLIKE);
        return integer;
    }

    //分页查询视频评论
    public PageBeanVo findVideoCommentList(Integer pageNumber, Integer pageSize, String videoId) {
        PageBeanVo pageBeanVo = commentService.findVideoCommentList(videoId, pageNumber, pageSize);
        //2.根据视频的评论查询个人信息
        List<Comment> comments = (List<Comment>) pageBeanVo.getItems();
        List<CommentVo> commentVos = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(comments)) {
            for (Comment comment : comments) {
                UserInfo userInfo = userInfoService.findById(comment.getUserId());

                CommentVo vo = new CommentVo();
                BeanUtil.copyProperties(userInfo, vo);
                BeanUtil.copyProperties(comment, vo);
                vo.setCreateDate(new SimpleDateFormat("yyyy-MM-dd").format(new Date(comment.getCreated())));

                // 视频评论的点赞数和是否点赞
                String key = StrUtil.format(ConstantUtil.VIDEO_LIKE, UserHolder.getId(), comment.getId());
                if (stringRedisTemplate.hasKey(key)) {
                    vo.setHasLiked(1);
                } else {
                    vo.setHasLiked(0);
                }
                commentVos.add(vo);
            }
        }


        pageBeanVo.setItems(commentVos);
        return pageBeanVo;
    }

    //发布视频评论
    @CacheEvict(value = "video", allEntries = true)
    public Map saveVideoComment(String videoId, String videoComment) {
        Comment comment = new Comment();
        comment.setCommentType(5);
        comment.setUserId(UserHolder.getId());
        comment.setContent(videoComment);
        comment.setPublishId(new ObjectId(videoId));
        if (comment.getContent() != null) {
            commentService.saveVideoComment(comment);
        }

        //判断用户权限
        UserFreeze userFreeze = userFreezeService.findById(UserHolder.get().getId());
        UserInfo userInfo = userInfoService.findById(UserHolder.get().getId());
        if (userFreeze != null) {
            Long timeRemaining = (userFreeze.getTime() - System.currentTimeMillis()) / 1000 / 60 / 60;
            if (Long.valueOf(userInfo.getUserStatus()) == 2 && userFreeze.getFreezingRange() == 2) {
                throw new RuntimeException("您的账号评论权限处于封禁状态中," + "还剩下" + timeRemaining + "小时解封");
            }
        }

        //发送MQ操作
        mqVideoManager.sendVideoMsg(videoId, MQVideoManager.VIDEO_COMMENT);
        return null;

    }


    //评论点赞
    @CacheEvict(value = "video", allEntries = true)
    public void likeVideoComment(String commentId) {
        //1.构建comment对象
        Comment comment = new Comment();
        //2.comment保存对象
        comment.setPublishId(new ObjectId(commentId));
        comment.setCommentType(6);
        comment.setUserId(UserHolder.getId());


        commentService.likeVideoComment(comment);


        //3.将数据存入redis中
        String format = StrUtil.format(ConstantUtil.VIDEO_LIKE, UserHolder.getId(), commentId);

        stringRedisTemplate.opsForValue().set(format, "6");  //值随便

        mqVideoManager.sendVideoMsg(commentId, MQVideoManager.VIDEO_LIKE);

    }

    //取消评论点赞
    @CacheEvict(value = "video", allEntries = true)
    public void dislikeVideoComment(String commentId) {
//1. 组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(commentId));//视频id
        comment.setCommentType(6);//点赞
        comment.setUserId(UserHolder.getId());//操作人id

        //2. 调用service完成取消点赞
        commentService.dislikeVideoComment(comment);

        //3. 向redis中删除点赞操作
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.VIDEO_LIKE, UserHolder.getId(), commentId));

        mqVideoManager.sendVideoMsg(commentId, MQVideoManager.VIDEO_DISLIKE);

    }
}
